package ink.xiaobaibai.provider;

import ink.xiaobaibai.token.JWTAuthenticationToken;
import ink.xiaobaibai.units.JWTUnit;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;

import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @description: JWT校验器
 * @author: 小白白
 * @create: 2021-05-14
 **/

public class TokenAuthenticationProvider implements AuthenticationProvider {

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {

        JWTAuthenticationToken jwtAuthenticationToken = (JWTAuthenticationToken) authentication;

        //开始检验,返回角色名称
        List<String> list = JWTUnit.validJWT(jwtAuthenticationToken.getJWT());
        if (JWTUnit.jwtThreadLocal.get() == null || JWTUnit.jwtThreadLocal.get().getClaim("userId") == null) {
            GrantedAuthority grantedAuthority = new SimpleGrantedAuthority("ROLE_ANONYMOUS");
            SecurityContextHolder.getContext().setAuthentication(new AnonymousAuthenticationToken("a", "a", Collections.singletonList(grantedAuthority)));
            return SecurityContextHolder.getContext().getAuthentication();
        }
        Integer userId = JWTUnit.jwtThreadLocal.get().getClaim("userId").asInt();
        if (list != null) {
            Set<SimpleGrantedAuthority> simpleGrantedAuthorityList = list.stream().map(SimpleGrantedAuthority::new).collect(Collectors.toSet());
            this.addOldAuthority(simpleGrantedAuthorityList);
            JWTAuthenticationToken newToken = new JWTAuthenticationToken(simpleGrantedAuthorityList, JWTUnit.jwtThreadLocal.get().getAudience().get(0), userId);
            newToken.setDetails(jwtAuthenticationToken.getDetails());
            //已认证
            newToken.setAuthenticated(true);
            return newToken;
        } else {
            GrantedAuthority grantedAuthority = new SimpleGrantedAuthority("ROLE_ANONYMOUS");
            SecurityContextHolder.getContext().setAuthentication(new AnonymousAuthenticationToken("a", "a", Collections.singletonList(grantedAuthority)));
            return SecurityContextHolder.getContext().getAuthentication();
        }
    }

    /**
     * 不遗漏旧的身份信息
     *
     * @param simpleGrantedAuthorityList
     */
    private void addOldAuthority(Set<SimpleGrantedAuthority> simpleGrantedAuthorityList) {
        if (SecurityContextHolder.getContext().getAuthentication() != null && SecurityContextHolder.getContext().getAuthentication().getAuthorities().size() != 0) {
            Collection<? extends GrantedAuthority> authorities = SecurityContextHolder.getContext().getAuthentication().getAuthorities();
            for (GrantedAuthority authority : authorities) {
                SimpleGrantedAuthority s = (SimpleGrantedAuthority) authority;
                simpleGrantedAuthorityList.add(s);
            }
        }
    }

    @Override
    public boolean supports(Class<?> aClass) {
        return JWTAuthenticationToken.class.isAssignableFrom(aClass);
    }

}
